package com.guiguli.a01polymorphism;

public class Test {
    public static void main(String[] args) {
        //创建三个对象并调用register方法

        Student s = new Student();
        s.setName("张三");
        s.setAge(18);

        Teacher t = new Teacher();
        t.setName("王建国");
        t.setAge(30);

        Administrator admin = new Administrator();
        admin.setName("管理员");
        admin.setAge(35);

        register(s);
        register(t);
        register(admin);

        //和c++的父类指针指向子类对象差不多
        Person p = new Student();
        p.setName("就这");
        p.setAge(200);
        p.show();
        System.out.println(p.str);  //多态调用成员变量会优先使用父类的 打印Person

        //p.print();    //多态的弊端，它无法调用父类没有，子类有的方法

        //解决方案 变回子类就行
        Student p2 = (Student)p;
        p2.print();

        //我们也可以直接一行
        ((Student) p).print();


        //我们可以通过instanceof关键字判断变量所记录的对象是不是某个类型
        //比如下面就是判断p是否是记录的Student
        if(p instanceof Student ) {
            Student ss = (Student) p;
            ss.print();
        } else if(p instanceof Teacher ){
            Teacher tt = (Teacher) p;
            tt.Te();
        }else if(p instanceof Administrator ){
            Administrator aa = (Administrator) p;
            aa.Ad();
        }
        else {
            System.out.println("没有这个类型 无法转换");
        }

        System.out.println("------------------------");

        //调用函数
        func(s);
        func(t);
        func(admin);

    }

    //这个方法既能接收老师 也能接收学生 还能接收管理员
    //我们只能把参数写成这三个类型的父类
    public static void register(Person p) {
        p.show();
    }

    //新特性
    //先判断p是否为Student类型 如果是强转为Student类型 转换后的变量名为s
    public  static void func(Person p){
        if(p instanceof Student s)      //相比于42行那个可以少写一行声明变量的代码
            s.print();
        else if(p instanceof Teacher t)
            t.Te();
        else if(p instanceof Administrator a)
            a.Ad();
        else
            System.out.println("没有这个类型 无法转换");
    }
}
